<!doctype html>
<html>
<head>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>xeokit Example</title>
    <link href="../css/pageStyle.css" rel="stylesheet"/>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.13.0/js/all.min.js"></script>
</head>
<body>
<input type="checkbox" id="info-button"/>
<label for="info-button" class="info-button"><i class="far fa-3x fa-question-circle"></i></label>
<canvas id="myCanvas"></canvas>
<div class="slideout-sidebar">
    <img class="info-icon" src="../../assets/images/performance_model_icon.png"/>
    <h1>SceneModel with SceneModelTransforms</h1>
    <p>Geometry instancing example with SceneModelTransforms</p>
    <ul>
        <li>
            <a href="../../docs/class/src/viewer/Viewer.js~Viewer.html"
               target="_other">Viewer</a>
        </li>
        <li>
            <a href="../../docs/class/src/viewer/scene/model/SceneModel.js~SceneModel.html"
               target="_other">SceneModel</a>
        </li>
        <li>
            <a href="../../docs/class/src/viewer/scene/model/SceneModelMesh.js~SceneModelMesh.html"
               target="_other">SceneModelMesh</a>
        </li>
        <li>
            <a href="../../docs/class/src/viewer/scene/model/SceneModelTransform.js~SceneModelTransform.html"
               target="_other">SceneModelTransform</a>
        </li>
    </ul>
</div>
</body>

<script type="module">

    //------------------------------------------------------------------------------------------------------------------
    // Import the modules we need for this example
    //------------------------------------------------------------------------------------------------------------------

    import {Viewer, SceneModel} from "../../dist/xeokit-sdk.min.es.js";

    //------------------------------------------------------------------------------------------------------------------
    // Create a Viewer and arrange the camera
    //------------------------------------------------------------------------------------------------------------------

    const viewer = new Viewer({
        canvasId: "myCanvas",
        transparent: true
    });

    viewer.scene.camera.eye = [-21.80, 4.01, 6.56];
    viewer.scene.camera.look = [0, -5.75, 0];
    viewer.scene.camera.up = [0.37, 0.91, -0.11];

    //------------------------------------------------------------------------------------------------------------------
    // Build a SceneModel representing a table with four legs, using geometry instancing
    //------------------------------------------------------------------------------------------------------------------

    const sceneModel = new SceneModel(viewer.scene, {
        id: "table",
        isModel: true, // <--------------------- Represents a model, registers SceneModel by ID on viewer.scene.models
        position: [0, 0, 0],
        scale: [1, 1, 1],
        rotation: [0, 0, 0],
        edges: true
    });

    //--------------------------------------------------------
    // Create a reusable geometry within the SceneModel
    // We'll instance this geometry by five meshes
    //--------------------------------------------------------

    sceneModel.createGeometry({

        id: "boxGeometry",

        // The primitive type - allowed values are "points", "lines" and "triangles".
        // See the OpenGL/WebGL specification docs for how the coordinate arrays are supposed to be laid out.
        primitive: "triangles",

        // The vertices - eight for our cube, each
        // one spanning three array elements for X,Y and Z
        positions: [
            1, 1, 1, -1, 1, 1, -1, -1, 1, 1, -1, 1, // v0-v1-v2-v3 front
            1, 1, 1, 1, -1, 1, 1, -1, -1, 1, 1, -1, // v0-v3-v4-v1 right
            1, 1, 1, 1, 1, -1, -1, 1, -1, -1, 1, 1, // v0-v1-v6-v1 top
            -1, 1, 1, -1, 1, -1, -1, -1, -1, -1, -1, 1, // v1-v6-v7-v2 left
            -1, -1, -1, 1, -1, -1, 1, -1, 1, -1, -1, 1,// v7-v4-v3-v2 bottom
            1, -1, -1, -1, -1, -1, -1, 1, -1, 1, 1, -1 // v4-v7-v6-v1 back
        ],

        // Indices - these organise the positions and and normals
        // into geometric primitives in accordance with the "primitive" parameter,
        // in this case a set of three indices for each triangle.
        //
        // Note that each triangle is specified in counter-clockwise winding order.
        //
        indices: [
            0, 1, 2, 0, 2, 3,            // front
            4, 5, 6, 4, 6, 7,            // right
            8, 9, 10, 8, 10, 11,         // top
            12, 13, 14, 12, 14, 15,      // left
            16, 17, 18, 16, 18, 19,      // bottom
            20, 21, 22, 20, 22, 23
        ]
    });

    //--------------------------------------------------------
    // Red table leg object
    //--------------------------------------------------------

    sceneModel.createTransform({
        id: "redLegTransform",
        position: [-4, -6, -4],
        scale: [1, 3, 1],
        rotation: [0, 0, 0]
    });

    sceneModel.createMesh({
        id: "redLegMesh",
        geometryId: "boxGeometry",
        transformId: "redLegTransform",
        color: [1, 0.3, 0.3]
    });

    sceneModel.createEntity({
        id: "redLeg",
        meshIds: ["redLegMesh"],
        isObject: true // <----------------- Represents an object, registers Entity by ID on viewer.scene.objects
    });

    //--------------------------------------------------------
    // Green table leg object
    //--------------------------------------------------------

    sceneModel.createTransform({
        id: "greenLegTransform",
        position: [4, -6, -4],
        scale: [1, 3, 1],
        rotation: [0, 45, 0]
    });

    sceneModel.createMesh({
        id: "greenLegMesh",
        geometryId: "boxGeometry",
        transformId: "greenLegTransform",
        color: [0.3, 1.0, 0.3]
    });

    sceneModel.createEntity({
        id: "greenLeg",
        meshIds: ["greenLegMesh"],
        isObject: true // <----------------- Represents an object, registers Entity by ID on viewer.scene.objects
    });

    //--------------------------------------------------------
    // Blue table leg
    //--------------------------------------------------------

    sceneModel.createTransform({
        id: "blueLegTransform",
        position: [4, -6, 4],
        scale: [1, 3, 1],
        rotation: [0, 0, 0]
    });

    sceneModel.createMesh({
        id: "blueLegMesh",
        geometryId: "boxGeometry",
        transformId: "blueLegTransform",
        color: [0.3, 0.3, 1.0]
    });

    sceneModel.createEntity({
        id: "blueLeg",
        meshIds: ["blueLegMesh"],
        isObject: true // <----------------- Represents an object, registers Entity by ID on viewer.scene.objects
    });

    //--------------------------------------------------------
    // Yellow table leg
    //--------------------------------------------------------

    sceneModel.createTransform({
        id: "yellowLegTransform",
        position: [-4, -6, 4],
        scale: [1, 3, 1],
        rotation: [0, 0, 0],
    });

    sceneModel.createMesh({
        id: "yellowLegMesh",
        geometryId: "boxGeometry",
        transformId: "yellowLegTransform",
        color: [1.0, 1.0, 0.0]
    });

    sceneModel.createEntity({
        id: "yellowLeg",
        meshIds: ["yellowLegMesh"],
        isObject: true // <----------------- Represents an object, registers Entity by ID on viewer.scene.objects
    });

    //--------------------------------------------------------
    // Purple table top
    //--------------------------------------------------------

    sceneModel.createTransform({
        id: "tableTopTransform",
        position: [0, -3, 0],
        scale: [6, 0.5, 6],
        rotation: [0, 0, 0]
    });

    sceneModel.createMesh({
        id: "purpleTableTopMesh",
        geometryId: "boxGeometry",
        transformId: "tableTopTransform",
        color: [1.0, 0.3, 1.0]
    });

    sceneModel.createEntity({
        id: "purpleTableTop",
        meshIds: ["purpleTableTopMesh"],
        isObject: true // <----------------- Represents an object, registers Entity by ID on viewer.scene.objects
    });

    //--------------------------------------------------------
    // Finalize this SceneModel.
    //
    // Internally, this builds any geometry batches or instanced
    // arrays that are currently under construction.
    //--------------------------------------------------------

    sceneModel.finalize();


    //------------------------------------------------------------------------------------------------------------------
    // Find scene graph nodes by their model and object IDs
    //------------------------------------------------------------------------------------------------------------------


    // Get some leg objects
    const table = viewer.scene.objects["table"];
    const redLeg = viewer.scene.objects["redLeg"];
    const greenLeg = viewer.scene.objects["greenLeg"];
    const blueLeg = viewer.scene.objects["blueLeg"];

    //------------------------------------------------------------------------------------------------------------------
    // Periodically update transforms on our scene nodes
    //------------------------------------------------------------------------------------------------------------------



    viewer.scene.on("tick", function () {

        // Rotate legs
        sceneModel.transforms["yellowLegTransform"].rotateY(0.5);
        sceneModel.transforms["redLegTransform"].rotateY(1.55);
        sceneModel.transforms["blueLegTransform"].rotateY(2.25);

        sceneModel.transforms["greenLegTransform"].rotateY(1);

        sceneModel.transforms["greenLegTransform"].translateX(0.05);
        sceneModel.transforms["redLegTransform"].translateX(-0.05);
        sceneModel.transforms["blueLegTransform"].translateZ(0.05);
        sceneModel.transforms["yellowLegTransform"].translateZ(0.05);
    });


</script>
</html>